package 反射;

import org.junit.Test;
import java.util.Random;

/*
    创建运行时类的对象
      创建类的对象:
         调用Class对象的newInstance()方法
      要 求:
         类必须有一个无参数的构造器
         类的构造器的访问权限需要足够

     不是没有无参的构造器就不能创建对象
        只要在操作的时候明确的调用类中的构造器,并将参数传递进去之后,才可以实例化操作,步骤如下:
           1、 通过Class类的getDeclaredConstructor(Class … parameterTypes)取得本类的指定形参类型的构造器
           2、 向构造器的形参中传递一个对象数组进去,里面包含了构造器中所需的各个参数
           3、 通过Constructor实例化对象
 */
public class Class05 {

    //通过反射创建对应的运行时类的对象
    @Test
    public void test1() throws IllegalAccessException, InstantiationException {
        Class<Person> personClass = Person.class;

        /*
            newInstance():调用此方法,创建运行时类的对象,内部调用了运行时类的空参的构造器
            要想此方法正常的创建运行时类的对象,要求:
                1、运行时类必须提供空参的构造器
                2、空参的构造器的访问权限得够,通常设置为public

            在JavaBean中要求提供一个public的空参的构造器,原因:
                1、在框架底层,一般都会通过反射调用空参构造器创建对象,然后在后面手动进行赋值,如果不提供会报错
                2、便于子类继承此运行时类时,默认调用super(),保证父类有此构造器
         */
        Person person = personClass.newInstance();
        System.out.println(person);
    }

    //体会Java的动态性,即在编译时无法确定要造哪个类的对象,只有在运行时才知道
    @Test
    public void test2(){
        int num = new Random().nextInt(2);//产生0或1的随机数
        String classPath = "";

        switch (num){
            case 0:
                classPath = "java.util.Date";
                break;
            case 1:
                classPath = "反射.Person";
                break;
        }

        try {
            Object instance = this.getInstance(classPath);
            System.out.println(instance);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }

    /*
        创建一个指定类的对象
            classPath:指定类的全类名
     */
    public Object getInstance(String classPath) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Class<?> clazz = Class.forName(classPath);
        return clazz.newInstance();
    }

}
